山姆再次勇闖黑森林,但是這次他大意了!
在旁埋伏的 Storm 跟 Lightning 趁山姆一不注意,使出了閃電暴風雨。
淋濕的山姆倒在地上。
幸好,這裡是從零開始的遊戲世界,山姆不只一條命。
於是山姆又重新站了起來,再次從起點出發。
PS. 這裡是開發 iOS 手機遊戲的系列文,如果還沒看過之前
劇情文章的朋友,歡迎先點這邊回顧唷!
目前主角一被怪物攻擊後,就會直接遊戲結束,但是這樣的節奏太快了,因此我們為主角新增生命值的機制,讓主角除了一開始的生命外,還有額外三條命 (共 4 條命)。
samLife
紀錄還有幾條生命lifeNode
、lifeIconNode
、lifeLabel
節點來顯示主角的圖示及剩下的生命值
lifeNode
裡"X \(self.samLife)"
,設定文字的顏色、尺寸、字體、位置,讓他垂直置中,水平置左,並加到 lifeNode
裡applySafeArea
方法,校正 position
,讓生命值的外層節點 lifeNode
的位置在地圖節點下方class GameScene: SKScene {
...
var samLife: Int = 3
var lifeNode: SKSpriteNode?
var lifeIconNode: SKSpriteNode?
var lifeLabel: SKLabelNode?
override func didMove(to view: SKView) {
...
self.lifeNode = SKSpriteNode(color: .clear, size: CGSize(width: CGFloat(self.size.width), height: CGFloat(30)))
self.lifeIconNode = SKSpriteNode(imageNamed: "sam_down_1")
self.lifeLabel = SKLabelNode(text: "X \(self.samLife)")
if let lifeNode = self.lifeNode, let lifeIconNode = self.lifeIconNode, let lifeLabel = self.lifeLabel {
lifeNode.anchorPoint = CGPoint(x: 0, y: 0.5)
self.addChild(lifeNode)
lifeIconNode.anchorPoint = CGPoint(x: 0, y: 0.5)
lifeIconNode.size.width = CGFloat(25)
lifeIconNode.size.height = CGFloat(25)
lifeIconNode.position = CGPoint(x: 5, y: 0)
lifeNode.addChild(lifeIconNode)
lifeLabel.fontColor = UIColor.white
lifeLabel.fontSize = CGFloat(22)
lifeLabel.fontName = "Copperplate"
lifeLabel.position = CGPoint(x: 35, y: 0)
lifeLabel.verticalAlignmentMode = .center
lifeLabel.horizontalAlignmentMode = .left
lifeNode.addChild(lifeLabel)
}
}
func applySafeArea() {
...
if let mapNode = self.mapNode, let scoreNode = self.scoreNode, let lifeNode = self.lifeNode {
mapNode.position = CGPoint(x: 0, y: -self.topSafeArea - scoreNode.size.height)
scoreNode.position = CGPoint(x: 0 ,y: -self.topSafeArea - scoreNode.size.height/2)
lifeNode.position = CGPoint(x: 0, y: -self.topSafeArea - scoreNode.size.height - mapNode.size.height - 15)
}
}
}
遊戲中已經出現顯示生命值的畫面囉!
有了計算剩餘生命值的變數後,可以依照剩餘的生命數量,讓遊戲重新開始或是真的遊戲結束。今天我們會先帶大家實作遊戲重新開始的部分,遊戲結束明天會再說明
在這邊我們可以建立遊戲重新開始的流程,需要做的事情有:
gameStop
方法 (在主角被怪物攻擊時會觸發),加上以下程式碼:
samLife
生命值減 1gameReset
gameReset
resetPosition
方法,將主角及怪物設定回到遊戲初始時的位置.ATTACK
self.isSamFall = false
class GameScene: SKScene {
func gameStop() {
...
self.samLife -= 1
if self.samLife < 0 {
print("遊戲結束")
} else {
Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(gameReset), userInfo: nil, repeats: false)
}
}
@objc func gameReset() {
self.lifeLabel?.text = "X \(self.samLife)"
for weather in self.weathers {
weather.resetPosition()
weather.setMode(mode: .ATTACK)
}
if let sam = self.sam {
sam.resetPosition()
}
self.isSamFall = false
}
}
在共用的角色類別中新增 resetPosition
方法
gridX
及 gridY
設定回初始格子點position
class GameCharacter {
...
func resetPosition() {
self.gridX = startGridX
self.gridY = startGridY
self.node.position = CGPoint(x: self.gridWH * self.startGridX + (self.gridWH/2), y: -self.gridWH * self.startGridY - (self.gridWH/2))
self.playAnimation(imageName: self.imageName, num: 2)
}
}
主角被攻擊 3 秒後,角色們都回到原本的位置,主角生命值減 1
考量到遊戲的流程是會不斷循環的,我們可以新增一個共用的遊戲開始
方法,在一進遊戲時、以及在主角減一條生命後,都可以呼叫
gameStart
方法,讓遊戲開始後有一段時間的緩衝,讓玩家可以看一下地圖,才遊戲開始。請設定 Timer,5 秒後執行遊戲開始動作 gameStartAction
didMove
的開始遊戲後的動作移到 gameStartAction
,包含設定角色們可以移動、讓怪物開始移動,以及產生隨機時間後變成玩耍模式的 Timerclass GameScene: SKScene {
...
func gameStart() {
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(gameStartAction), userInfo: nil, repeats: false)
}
@objc func gameStartAction() {
for weather in self.weathers {
weather.setCanMove(isCanMove: true)
weather.startMove(direction: .NONE)
}
if let sam = self.sam {
sam.setCanMove(isCanMove: true)
}
let randomTime = Int.random(in: 10...50)
self.randomTimer = Timer.scheduledTimer(timeInterval: TimeInterval(randomTime), target: self, selector: #selector(attackToPlayModeAction), userInfo: nil, repeats: false)
}
}
gameStart
方法gameRestart
裡呼叫 gameStart
class GameScene: SKScene {
...
override func didMove(to view: SKView) {
...
self.gameStart()
}
@objc func gameRestart() {
...
self.gameStart()
}
}
遊戲成功加上生命值機制了!在生命值沒有歸零前,可以不斷重新開始遊戲,之前收集的水晶跟分數也都還會保留
目前已經加上重新開始遊戲的流程了,明日會繼續將遊戲結束後的流程加上
我們預計在遊戲結束時,會切換到另外一個場景,並且顯示玩家這場的遊戲得分,再加上重新開始遊戲的按鈕
我們明日見囉~